iT邦幫忙

2022 iThome 鐵人賽

DAY 10
0

https://ithelp.ithome.com.tw/upload/images/20220912/20151958IFjRs0xIZ4.png Medium 好讀版

此系列文章是以我的業餘專案: Kimoji 作為範例。
這款以純 Jetpack Compose 撰寫的 side project,已經在 Google Play 上架。 歡迎試玩!

https://ithelp.ithome.com.tw/upload/images/20220907/20151958vXuPLv4aki.png 立馬下載 https://ithelp.ithome.com.tw/upload/images/20220907/20151958LtM1NGErzK.png 索取兌換碼

Recomposition 會盡可能選擇略過

當部分 UI invalid 時,Compose 會盡可能只針對需要更新的部分進行 recompose。舉例來說,Compose 可能會重新執行一個 button 的 composable,而不執行該元件在 UI 樹狀結構中任何上層或下層的 composables。

每個 composable function 和 lambda 都可能會自行 recompose。下面的範例顯示了 recomposition 在 render 清單時如何略過部分元件:

/**
 * Display a list of diaries the user can click with a header
 */
@Composable
fun Journal(
    header: String,
    diaries: List<String>,
    onDiaryClick: (String) -> Unit
) {
    Column {
        // this will recompose when [header] changes, but not when [diaries] changes
        Text(header, style = MaterialTheme.typography.h5)
        Divider()

        // LazyColumn is the Compose version of a RecyclerView.
        // The lambda passed to items() is similar to a RecyclerView.ViewHolder.
        LazyColumn {
            items(diaries) { notes ->
                // When an item's [notes] updates, the adapter for that item
                // will recompose. This will not recompose when [header] changes
                DiaryItem(notes, onDiaryClick)
            }
        }
    }
}

/**
 * Display a single diary the user can click.
 */
@Composable
private fun DiaryItem(notes: String, onClick: (String) -> Unit) {
    Text(notes, Modifier.clickable(onClick = { onClick(notes) }))
}

上面這段 code 的各個 scope 都可能是 recomposition 期間唯一會執行的項目。當 header 變更時,Compose 可能會直接執行 Column 的 lambda,而不會執行它的任何的 parent。另外,在執行 Column 時,如果 diaries 沒有變更,Compose 可能會選擇略過 LazyColumn 的 items。

同樣地,執行所有 composable function 或 lambda 都不應該有任何 side-effect。當我們需要執行 side-effect 時,需透過 callback 觸發。

Recomposition 具有 optimistic 的特性

只要 Compose 認為 composable 的參數可能有變動,即會啟動 recomposition。Recomposition 具有「optimistic」的特性,這表示 Compose 預期在參數再次變更前可以完成 recomposition。如果參數在 recomposition 完成前就「有變動」,Compose 可能會取消這個 recomposition,並使用新的參數重新啟動 recomposition。

Recomposition 取消後,Compose 會捨棄 recomposition 中的 UI 樹狀結構。如果顯示的 UI 有任何 side-effect,即使 composition 取消,系統仍會套用 side-effect。這可能會導致 app 狀態不一致。

要確認所有 composable function 和 lambda 皆符合 idempotent、無 side-effect 的條件,以處理具有 optimistic 特性的 recomposition。

此系列文章是以我的業餘專案:Kimoji 為範例。

Kimoji 是一款心情日記 App,讓你用可愛的 emoji 來撰寫你的心情日記。現在就來試試這款設計精美的微日記吧!

https://ithelp.ithome.com.tw/upload/images/20220907/20151958vXuPLv4aki.png 立馬下載 https://ithelp.ithome.com.tw/upload/images/20220907/20151958LtM1NGErzK.png 索取兌換碼

Reference: https://developer.android.com/jetpack/compose/mental-model


上一篇
Composable function 的特性
下一篇
Composable functions 可以平行執行
系列文
Kimoji:以 Jetpack Compose 實作一款「心情日記」應用30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言